package com.hdy.framework.memcached.xmemcached.aop;

import java.lang.reflect.Method;

import net.rubyeye.xmemcached.MemcachedClient;

import org.aspectj.lang.ProceedingJoinPoint;
import org.aspectj.lang.annotation.Around;
import org.aspectj.lang.annotation.Aspect;

import com.hdy.framework.memcached.xmemcached.anotation.XMemcachedParam;
import com.hdy.framework.memcached.xmemcached.utils.MemcachedClientUtils;
import com.hdy.utils.log4j.Log4jUtils;

/*
	by 何栋宇
	2013-1-30
 */
@Aspect
public class CacheAround {
	//切入点表达式
//	@Around("execution(* com.hdy.demo.aop.service.impl.MyAopServiceImpl.*(..))")
//	@Around("execution(public * *(..))")
	//凡是方法上有此注解的将被拦截
	@Around("@annotation(com.hdy.framework.memcached.xmemcached.anotation.XMemcachedParam)")
	public Object around(ProceedingJoinPoint pj) throws Throwable{
		//目标方法名称
		String targetMethodName = pj.getSignature().getName();
		//目标类名称
		String targetClassName = pj.getTarget().getClass().getName();
		//目标方法参数
		Object[] args=pj.getArgs();
//		args.toString();
		//失效时间定义
		int expire=0;
		//是否配置缓存
		boolean  isCacheSet=false;
		//反射获取目标类
		Object c = Class.forName(targetClassName).newInstance();
		//目标类中的所有声明的方法
		Method[] methodArray=c.getClass().getDeclaredMethods();
		//遍历找到当前被aop的方法：找到它的anotation配置的值
		for(int i=0;i<methodArray.length;i++){
			Method method=methodArray[i];
			//如果此方法被配置的@MemcacheParam
			if(method.isAnnotationPresent(XMemcachedParam.class)){
				//类中所有方法匹配到当前执行方法
				if(method.getName().equals(targetMethodName)){
					XMemcachedParam memcacheParam = method.getAnnotation(XMemcachedParam.class);
					expire = memcacheParam.expire();
					isCacheSet=true;
					break;
				}
			
			}
		}
		if(!isCacheSet || expire<=0){//没有设置缓存 设置缓存错误
			return pj.proceed();//直接执行完方法返回
		}else{
			String memcacheKey=buildeKey(targetClassName,targetMethodName,args);
			return dealMemcache(pj, memcacheKey, expire);
		}
		
//		//控制新参数
//		String param1="屏蔽外面传入的一切参数";
//		//注释这一行则方法都不会被调用
//		Object returnParam = pj.proceed(new String[]{param1,param1});
		//被调用的方法只会返回这个参数
//		return returnParam;
	}
	private Object dealMemcache(ProceedingJoinPoint pj,String memcacheKey,int expire) 
			{
		Log4jUtils.getLog(CacheAround.class).error("失效时间："+expire);
//		System.out.println("失效时间："+expire);
		//构建memcache 的 key值
		Log4jUtils.getLog(CacheAround.class).error("memcache key:"+memcacheKey);
		//下面的逻辑是在缓存中查询是否存在此key值的缓存
		Object cacheObj=null;
		MemcachedClient client= MemcachedClientUtils.get();
		boolean memcacheException=false;
		try{
			cacheObj = client.get(memcacheKey);
		}catch(Exception e){
			e.printStackTrace();
			Log4jUtils.getLog(CacheAround.class).error("memcache服务器异常...");
			memcacheException=true;
		}
		//是否需要重置缓存值
		if(cacheObj==null){//不在缓存中
			Object returnParam=null;
			//直接调用目标方法
			try {
				returnParam=pj.proceed();
				if(!memcacheException){
					//根据 memcacheKey expire来重设缓存
					client.set(memcacheKey, expire, returnParam);
				}
			} catch (Throwable e) {
				e.printStackTrace();
			}
			return returnParam;
		}else{
			//返回缓存内的值
			return cacheObj;
		}
	}
	//key值由类名 方法名 参数构成
	private String buildeKey(String targetClassName,String targetMethodName,Object[] args){
		StringBuilder memcacheKey = new StringBuilder();
		memcacheKey.append(targetClassName).append(targetMethodName).append("_");
		if(args!=null && args.length>0){
			for(int i=0,size=args.length;i<size;i++){
				memcacheKey.append(args[i].toString()).append("_");
			}
		}
		return memcacheKey.toString();
	}
}
